<template>
  <div class="base-form">
    <!-- @submit.prevent
      @keyup.enter="submitForm" -->
    <el-form v-bind="getBindValue" ref="ruleForm" :model="formInline" :label-width="labelWidth" :label-position="labelPosition" @submit.prevent>
      <component
        :is="isCol && !item.hidden ? ElCol : ''"
        v-bind="{ ...getColValue(item) }"
        v-for="(item, $index) in schema"
        :key="$index"
        :span="(item.colProps && item.colProps.span) || 6"
      >
        <el-form-item v-if="!item.hidden" v-bind="{ ...getFormItemValue(item) }" :class="isCol ? '' : 'col25'" :label="item.label" :prop="item.field">
          <!-- label -->
          <template #label>
            <div class="titleLable" :style="{ cursor: item.label.length > 6 ? 'pointer' : '' }">
              <el-popover :disabled="item.label.length <= 6" placement="top-start" :width="200" trigger="hover" :content="item.label">
                <template #reference>
                  <div class="mx-w-90">
                    {{ item.label }}
                  </div>
                </template>
              </el-popover>
            </div>
          </template>
          <template v-if="slots && slots[item.field]">
            <slot :name="item.field" :model="formInline" :item="item" :field="item.field"></slot>
          </template>
          <template v-else>
            <!-- 单选框 -->
            <template v-if="item.component === 'Radio' && item.options">
              <el-radio
                v-for="v in item.options"
                v-bind="{ ...item.componentProps }"
                :key="`Radio${v.value}`"
                v-model="formInline[item.field]"
                :label="item.optionsField && item.optionsField.valueField ? v[item.optionsField.valueField] : v.value"
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              >
                {{ item.optionsField && item.optionsField.labelField ? v[item.optionsField.labelField] : v.label }}
              </el-radio>
            </template>
            <!-- 单选框组 -->
            <template v-else-if="item.component === 'RadioGroup' && item.options">
              <el-radio-group v-model="formInline[item.field]">
                <el-radio
                  v-for="v in item.options"
                  v-bind="{ ...item.componentProps }"
                  :key="`RadioGroup${v.value}`"
                  :label="item.optionsField && item.optionsField.valueField ? v[item.optionsField.valueField] : v.value"
                  @change="
                    () => {
                      changeVal(item)
                    }
                  "
                >
                  {{ item.optionsField && item.optionsField.labelField ? v[item.optionsField.labelField] : v.label }}
                </el-radio>
              </el-radio-group>
            </template>
            <!-- 多选框 -->
            <template v-else-if="item.component === 'Checkbox' && item.options">
              <el-checkbox
                v-for="v in item.options"
                v-bind="{ ...item.componentProps }"
                :key="`Checkbox${v.value}`"
                v-model="formInline[item.field]"
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              >
                {{ item.optionsField && item.optionsField.labelField ? v[item.optionsField.labelField] : v.label }}
              </el-checkbox>
            </template>
            <!-- 多选框组 -->
            <template v-else-if="item.component === 'CheckboxGroup' && item.options">
              <el-checkbox-group v-model="formInline[item.field]">
                <el-checkbox
                  v-for="v in item.options"
                  v-bind="{ ...item.componentProps }"
                  :key="`CheckboxGroup${v.value}`"
                  :label="item.optionsField && item.optionsField.valueField ? v[item.optionsField.valueField] : v.value"
                  @change="
                    () => {
                      changeVal(item)
                    }
                  "
                >
                  {{ item.optionsField && item.optionsField.labelField ? v[item.optionsField.labelField] : v.label }}
                </el-checkbox>
              </el-checkbox-group>
            </template>
            <!-- 文本输入框 -->
            <template v-else-if="item.component === 'Input'">
              <el-input
                v-model.trim="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                :placeholder="t('keys.pleaseEnter')"
                @keydown.enter="submitEnterForm"
                clearable
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              />
            </template>
            <!-- 数字输入框 -->
            <template v-else-if="item.component === 'InputNumber'">
              <el-input-number
                v-model="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                :placeholder="t('keys.pleaseEnter')"
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              />
            </template>
            <!-- 下拉框的组件二次封装-->
            <template v-else-if="item.component === 'Select'">
              <!-- @change="
                  (val) => {
                    formInline[item.field] = val
                  } -->
              <lov
                v-if="item.lovCode && !item.options?.length"
                v-bind="{ ...item.componentProps }"
                :value="formInline[item.field]"
                :lovCode="item.lovCode"
                @change="
                  (val) => {
                    changeSelectVal(val, '', item)
                  }
                "
              >
              </lov>
              <el-select
                v-else
                v-model="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                placeholder="请选择"
                clearable
                style="width: 100%;"
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              >
                <el-option
                  class="opsSpan"
                  v-for="v in item.options"
                  :key="`Select${v.value}`"
                  :label="item.optionsField && item.optionsField.labelField ? v[item.optionsField.labelField] : v.label"
                  :value="item.optionsField && item.optionsField.valueField ? v[item.optionsField.valueField] : v.value"
                />
              </el-select>
            </template>
            <!-- 下拉分页 -->
            <template v-else-if="item.component === 'pageSelect'">
              <!-- @pageChange="
                  (val, assignment) => {
                    formInline[assignment] = val
                  }" -->
              <pageSelect
                :modelValue="formInline[item.field]"
                :selectObj="item.componentProps"
                v-bind="{ ...item.componentProps }"
                @pageChange="
                  (val, assignment) => {
                    changeSelectVal(val, assignment, item)
                  }
                "
              ></pageSelect>
            </template>
            <!-- 级联选择器 -->
            <template v-else-if="item.component === 'Cascader' && item.options">
              <el-cascader
                v-model="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                :options="item.options"
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              />
            </template>
            <!-- 开关 -->
            <template v-else-if="item.component === 'Switch'">
              <el-switch
                v-model="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              />
            </template>
            <!-- 时间选择器 -->
            <template v-else-if="item.component === 'TimePicker'">
              <el-time-select
                v-model="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              />
            </template>
            <!-- 日期选择器 -->
            <template v-else-if="item.component === 'DatePicker'">
              <el-date-picker
                v-model="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                @change="
                  () => {
                    changeVal(item)
                  }
                "
              />
            </template>
            <!-- 日期区间选择器 请使用post请求 暂时测试了列表的搜索，其他功能请自测-->
            <template v-else-if="item.component === 'DateTimeRange'">
              <el-date-picker
                style="width: calc(100% - 20px) !important;"
                v-model="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                type="daterange"
                :placeholder="t('keys.please_select_date_tips')"
                format="YYYY-MM-DD"
                value-format="YYYY-MM-DD"
                :range-separator="t('keys.To')"
                :start-placeholder="t('keys.StartDate')"
                :end-placeholder="t('keys.EndDate')"
                @change="
                  () => {
                    changeDateTimeRangeVal(item, formInline[item.field])
                  }
                "
              />
            </template>
            <template v-else-if="item.component === 'lovView'">
              <el-input
                v-model.trim="formInline[item.field]"
                v-bind="{ ...item.componentProps }"
                :placeholder="t('keys.pleaseClick')"
                style="width: 100%"
                readonly
                @click="inputClick(item.lovViewCode, 'lovViewRef' + item.field)"
              >
                <template #suffix>
                  <el-icon class="closeval" v-if="formInline[item.field]" @click="closeClickVal(item.field)">
                    <CircleClose />
                  </el-icon>
                </template>
              </el-input>
              <!-- :ref="'lovViewRef' + item.field" -->
              <!-- @lovChange="lovViewChange" -->
              <lovView
                ref="lovViewRef"
                :showFieldFlag="true"
                :valueFieldFlag="true"
                :lovViewCode="item.lovViewCode"
                :Preview="item.Preview"
                :checkboxFlag="item.checkboxFlag"
                @lovChange="
                  (val, keyP) => {
                    formInline[item.field] = val[keyP]
                  }
                "
              >
              </lovView>
            </template>
          </template>
        </el-form-item>
        <!-- <div style="display: inline-block">
          <slot v-if="$index === schema.length - 1"></slot>
        </div> -->
      </component>
      <el-col :span="6" v-if="optionConfig.type == 'search'">
        <slot name="search"></slot>
      </el-col>
    </el-form>
  </div>
</template>

<script setup name="BaseForm">
/* eslint-disable */
import { computed, onMounted, useAttrs, ref, unref, watch, getCurrentInstance, nextTick, useSlots } from 'vue'
import lov from '@/components/lov'
import pageSelect from '@/components/page-select'
import lovView from 'components/lov-view'
import { ElCol } from 'element-plus'
import { ElRow } from 'element-plus'
import { deepClone } from '@/utils/index'
import { set as objectSet } from 'lodash-es'
import { useI18n } from 'vue-i18n'
const { t } = useI18n() // 中英文
const root = getCurrentInstance().proxy
const attrs = useAttrs()
const slots = useSlots()

const ruleForm = ref(null)

const emit = defineEmits(['register', 'submitForm'])

const submitEnterForm = (e) => {
  let keyCode = window.event ? e.keyCode : e.whitch
  if (keyCode == 13) {
    // 回车搜索事件 提交传递数据
    emit('submitForm')
  }
}
const props = defineProps({
  // 布局展示的数据
  schema: {
    type: Array,
    required: true,
    default: () => []
  },
  // 表单域标签的宽度，例如 '120px'。作为 Form 直接子元素的 form-item 会继承该值。支持 auto。
  labelWidth: {
    type: String,
    default: '120px'
  },
  labelPosition: {
    type: String,
    default: 'left'
  },
  // 是否需要栅格
  isCol: {
    type: Boolean,
    default: true
  },
  optionConfig: {
    type: Object,
    default: () => {}
  }
})

const formInline = ref({})
const schemaProps = ref(props.schema)
// 屏幕宽度
const windowWidth = ref(0)
const colWidth = ref(null)
const lovViewRef = ref()

onMounted(() => {
  getWindowResize()
  window.addEventListener('resize', getWindowResize)
})
const getWindowResize = function() {
  windowWidth.value = window.innerWidth - 300
  colWidth.value = windowWidth.value / 4
}

// 值集视图弹框
function inputClick(code) {
  const lovView = unref(lovViewRef)
  nextTick(() => {
    lovView[0].showDrawer(code)
  })
}
// 删除值集视图
function closeClickVal(field) {
  formInline.value[field] = ''
}

watch(
  schemaProps,
  (val) => {
    setFormValue(val)
  },
  {
    immediate: true,
    deep: true
  }
)
watch(
  formInline.value,
  () => {
    setTimeout(() => {
      emit('register', ruleForm.value, root, formInline.value)
    }, 1000)
  },
  {
    immediate: true,
    deep: true
  }
)

function setFormValue(val) {
  for (const v of val) {
    if (!v.hidden) {
      const formValue = formInline.value[v.field]
      formInline.value[v.field] = formValue !== void 0 ? formValue : v.value || ''
    }
  }
}
const getBindValue = computed(() => {
  const bindValue = { ...attrs, ...props }
  delete bindValue.schema
  for (const key in bindValue) {
    if (key === 'labelWidth') {
      bindValue['label-width'] = bindValue[key]
      delete bindValue[key]
    }
    if (key === 'labelPosition') {
      bindValue['label-position'] = bindValue[key]
      delete bindValue[key]
    }
  }
  delete bindValue.labelWidth
  delete bindValue.isCol
  delete bindValue.isSearch
  delete bindValue.optionConfig
  return bindValue
})

function getColValue(item) {
  const delArr = ['span']
  const obj = deepClone(item.colProps || {})
  for (const key in obj) {
    if (delArr.indexOf(key) !== -1) {
      delete obj[key]
    }
  }
  return obj
}

function getFormItemValue(item) {
  const delArr = ['label', 'prop']
  const obj = deepClone(item.formItemProps || {})
  for (const key in obj) {
    if (delArr.indexOf(key) !== -1) {
      delete obj[key]
    }
  }
  return obj
}
// lov静态值集或下拉分页组件赋值
const changeSelectVal = (val, key, item) => {
  if (key) {
    formInline.value[key] = val
  } else {
    formInline.value[item.field] = val
  }

  emit('register', ruleForm.value, root, formInline.value, true)
}
// 输入或选择值的变化
function changeVal(item) {
  if (item.onChange) {
    item.onChange({
      field: item.field,
      value: unref(formInline)[item.field]
    })
  }
  // 下拉框实时选择后筛选结果
  if (item.options?.length) {
    nextTick(() => {
      emit('register', ruleForm.value, root, formInline.value, true)
    })
  }
}

function changeDateTimeRangeVal(item, value) {
  if (item.component == 'DateTimeRange' && value) {
    emit('register', ruleForm.value, root, formInline.value, true)
  } else {
    nextTick(() => {
      emit('register', ruleForm.value, root, formInline.value, true)
    })
  }
}

function setProps(field, val, path) {
  schemaProps.value.map((item, i) => {
    if (item.field === field) {
      schemaProps.value[i] = objectSet(item, path, val)
    }
  })
}

function addSchema(formCong, index) {
  if (index !== void 0) {
    schemaProps.value.splice(index, 0, formCong)
    return
  }
  schemaProps.value.push(formCong)
}

function delSchema(index) {
  if (index !== void 0) {
    schemaProps.value.splice(index, 1)
    return
  }
  schemaProps.value.pop()
}

function setValue(field, value) {
  formInline.value[field] = value
}

defineExpose({
  setProps,
  addSchema,
  delSchema,
  setValue
})
</script>
<style lang="scss">
.base-form {
  .closeval {
    display: none;
    cursor: pointer;
  }
  .el-input__wrapper:hover .closeval {
    display: block;
  }
  .el-col-6 {
    width: 25%;
    min-width: 347px;
    display: inline-block;
  } 
  .mx-w-90 {
    max-width: 90px;
    overflow: hidden;
    display: block;
    white-space: nowrap;
    text-overflow: ellipsis;
    -o-text-overflow: ellipsis;
  }
  .el-form-item {
    margin-bottom: 8px;
    padding-right: 10px;
    // 默认宽度为 108px
    .el-form-item__label {
      justify-content: left;
      padding: 0;
      background: #fafafa;
      // lable 搜索字段文字居中
      line-height: 30px !important;
    }
    .el-form-item__content {
      display: block;
      width: calc(100% - 108px);
    }
  }
}
.opsSpan {
  max-width: 500px;
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
</style>
